﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace TryHelp
{
    [Serializable]
    public class DNetResponse
    {
        /// <summary>
        /// 用于承载向客户端返回的数据
        /// </summary>
        private IDictionary<string, object> KVData = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        public DNetResponse(bool _success = true)
        {
            Success = _success;
        }
        /// <summary>
        /// 标识请求是否处理成功 默认成功
        /// </summary>
        public bool Success { get; set; }
        /// <summary>
        /// 如果处理失败时用于返回错误编码
        /// </summary>
        public string ErrorCode { get; set; }
        /// <summary>
        /// 如果处理失败时用于返回详细的错误消息
        /// 默认值：系统错误，请联系系统管理员
        /// </summary>
        public string ErrorDetail { get; set; }
        /// <summary>
        /// 用于返回一个消息信息
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 用于承载向客户端返回的数据
        /// </summary>
        public object Data { get; set; }

        public void AppendErrorDetail(string error)
        {
            if (ErrorDetail == null) ErrorDetail = string.Empty;
            ErrorDetail += error;
            Success = false;
        }

        public IDictionary<string, object> GetKVData()
        {
            return KVData;
        }
        public object GetData(string key)
        {
            if (this.KVData.ContainsKey(key))
            {
                return KVData[key];
            }
            return null;
        }
        public void SetData(string key, object data)
        {
            if (this.KVData.ContainsKey(key))
            {
                KVData[key] = data;
            }
            else
            {
                KVData.Add(key, data);
            }
        }
    }

    [Serializable]
    public class DNetRequest
    {
        private IDictionary<string, object> KVData = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        public DNetRequest()
        {

        }
        /// <summary>
        /// DNetRequest
        /// </summary>
        /// <param name="action">要请求的Action</param>
        public DNetRequest(string action)
        {
            if (string.IsNullOrWhiteSpace(action))
            {
                throw new Exception("请提供要请求的action");
            }
            this.Action = action.Trim();
        }
        /// <summary>
        /// 获取请求的Action
        /// </summary>
        public string Action { get; set; }
        /// <summary>
        /// 该请求要发送的数据
        /// </summary>
        public object Data { get; set; }
        public IDictionary<string, object> GetKVData()
        {
            return KVData;
        }
        public void ClearData()
        {
            KVData.Clear();
        }
        public object GetData(string key)
        {
            if (this.KVData.ContainsKey(key))
            {
                return KVData[key];
            }
            return null;
        }
        public void SetData(string key, object data)
        {
            if (this.KVData.ContainsKey(key))
            {
                KVData[key] = data;
            }
            else
            {
                KVData.Add(key, data);
            }
        }

        public  string GetQueryString()
        {
            
            if (KVData == null || KVData.Count == 0)
            {
                return "";
            }

            StringBuilder sb = new StringBuilder();

            var i = 0;
            foreach (var kv in KVData)
            {
                i++;
                sb.AppendFormat("{0}={1}", kv.Key, kv.Value);
                if (i < KVData.Count)
                {
                    sb.Append("&");
                }
            }

            return sb.ToString();
        }
    }

    public static class RO
    {

        private static IFormatter formatter = new BinaryFormatter();
        /// <summary>
        /// 每次请求都要发送的参数
        /// </summary>
        public static Dictionary<string, object> InitRequestParams = new Dictionary<string, object>();
        

        private static DNetResponse _Post(DNetRequest dnetRequest, string url, Encoding encoding = null, int timeout = 360)
        {
            DNetResponse res = null;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.KeepAlive = false;//如果不加此设置的话，频繁请求时可能会出现错误：基础连接已经关闭: 服务器关闭了本应保持活动状态的连接
                using (MemoryStream stream = new MemoryStream())
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(dnetRequest.GetQueryString());
                    request.Method = "POST";
                    request.Proxy = null;
                    request.ReadWriteTimeout = timeout * 1000;
                    request.Timeout = timeout * 1000;
                    request.ContentType = "application/x-www-form-urlencoded";
                    //request.ContentType = "application/octet-stream";
                    request.GetRequestStream().Write(bytes, 0, bytes.Length);
                }
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        try
                        {
                            using (Stream responseStream = response.GetResponseStream() ?? new MemoryStream())
                            {
                                using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.GetEncoding("utf-8")))
                                {
                                    res = new DNetResponse();
                                    res.Data = myStreamReader.ReadToEnd();                                    
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            res = new DNetResponse(false);
                            res.ErrorCode = "RESPONSE_DATA_INVALID";
                            res.ErrorDetail = "收到了正确的响应状态，但是在解析数据时出错";
                        }
                    }
                    else
                    {
                        res = new DNetResponse(false);
                        res.ErrorCode = "RESPONSE_STATUSCODE_ERROR";
                        res.ErrorDetail = "未能收到正确的响应状态";
                    }
                }
                if (request != null) request.Abort();
            }
            catch (Exception ex)
            {
                res = new DNetResponse(false);
                res.ErrorCode = "RESPONSE_EXCEPT";
                res.ErrorDetail = "请求出现异常\n" + ex.Message + "\n" + ex.StackTrace;
            }
            if (res == null)
            {
                res = new DNetResponse(false);
                res.ErrorCode = "RESPONSE_IS_NULL";
                res.ErrorDetail = "未能收到有效的返回数据";
            }
            return res;
        }


        /// <summary>
        /// 请求数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name=""></param>
        /// <param name="url"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public static DNetResponse Post(this DNetRequest request, string url,Encoding encoding=null, int timeOut = 360)
        {
            DNetResponse response = null;
            response = _Post(request, url,  encoding, timeOut);
            return response;
        }

        /// <summary>
        /// 请求数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name=""></param>
        /// <param name="url"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public static DNetResponse Post<T>(this DNetRequest request, string url, Encoding encoding = null, int timeOut = 360)
        {
            DNetResponse response = null;
            response = _Post(request, url, encoding, timeOut);
            if (response.Success)
            {
                response.Data = JsonConvert.DeserializeObject<T>(response.Data.ToString());
            }
            return response;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="url"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public static async Task<DNetResponse> PostAsync(this DNetRequest request, string url, Encoding encoding=null, int timeOut = 360)
        {
            DNetResponse response = null;
            await Task.Run(() =>
            {
                response = _Post(request, url,  encoding, timeOut);
            });
            return response;
        }
        public static async Task<DNetResponse> PostAsync<T>(this DNetRequest request, string url, Encoding encoding = null, int timeOut = 360)
        {
            DNetResponse response = null;
            await Task.Run(() =>
            {
                response = _Post(request, url, encoding, timeOut);
                if (response.Success)
                {
                    response.Data = JsonConvert.DeserializeObject<T>(response.Data.ToString());
                }
            });
            return response;
        }


        /// <summary>
        /// md5加密
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string EncryptWithMD5(string source)
        {
            byte[] sor = Encoding.UTF8.GetBytes(source);
            MD5 md5 = MD5.Create();
            byte[] result = md5.ComputeHash(sor);
            StringBuilder strbul = new StringBuilder(40);
            for (int i = 0; i < result.Length; i++)
            {
                strbul.Append(result[i].ToString("x2"));//加密结果"x2"结果为32位,"x3"结果为48位,"x4"结果为64位

            }
            return strbul.ToString();
        }

    }
}
